﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Net.Mail;
using TBM.Filters;
using TBM.Attributes;
using TBM.Tools;

namespace TBM.Controllers
{
    public partial class UserController : MasterController
    {
        [Description("用户列表")]
        [TBMAuthorize("用户管理", "用户列表")]
        public ActionResult Index()
        {
            List<Models.User> users = new List<Models.User>();

            cmd.CommandText = "p_GetUsers";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Clear();

            cmd.Parameters.Add("@LikeName", SqlDbType.NVarChar, 32);
            cmd.Parameters.Add("@Group", SqlDbType.VarChar, 15);
            cmd.Parameters.Add("@IsActive", SqlDbType.Bit);
            cmd.Parameters.Add("@PageSize", SqlDbType.Int);
            cmd.Parameters.Add("@CurrPage", SqlDbType.Int);
            cmd.Parameters.Add("@RecordCount", SqlDbType.Int);

            PageNavigationBar pnb = new PageNavigationBar("p", Core.Config.PageSize, Core.Config.DisplayPageCount);

            cmd.Parameters["@RecordCount"].Direction = ParameterDirection.Output;
            cmd.Parameters["@PageSize"].Value = pnb.PageSize;
            cmd.Parameters["@CurrPage"].Value = pnb.CurrPage;
            string group = Request["group"] != null ? Request["group"].ToString() : null;
            if (!String.IsNullOrEmpty(group)) cmd.Parameters["@Group"].Value = group;
            string likeName = Request["like"] != null ? Request["like"].ToString() : null;
            if (!String.IsNullOrEmpty(likeName)) cmd.Parameters["@LikeName"].Value = likeName;
            bool? active = null;
            bool _active = false;
            if (Request["active"] != null && bool.TryParse(Request["active"].ToString(), out _active))
            {
                active = _active;
            }
            if (active != null) cmd.Parameters["@IsActive"].Value = active;


            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    users.Add(new Models.User
                    {
                        UID = dr["UID"].ToString(),
                        Groups = dr["Groups"].ToString(),
                        CNName = (bool)dr["CNName"],
                        FirstName = dr["FirstName"].ToString(),
                        LastName = dr["LastName"].ToString(),
                        PicUrl = dr["PicUrl"].ToString(),
                        Email = dr["Email"].ToString(),
                        Phone = dr["Phone"].ToString(),
                        QQ = dr["QQ"].ToString(),
                        RegisterDate = Convert.ToDateTime(dr["RegisterDate"]),
                        IsActive = (bool)dr["IsActive"],
                        Memo = dr["Memo"].ToString()
                    });
                }
            }

            pnb.Count = (int)cmd.Parameters["@RecordCount"].Value;
            ViewBag.PageNav = pnb.Create();

            if (IsAjaxRequest)
            {
                return PartialView("IndexTable", users);
            }

            cmd.Parameters.Clear();
            cmd.CommandText = "select '' as GID, '所有组' as GroupName, '' as Descr union all select GID, GroupName, Descr from dbo.Groups";
            cmd.CommandType = CommandType.Text;

            List<Models.Group> Groups = new List<Models.Group>();

            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    Groups.Add(new Models.Group
                    {
                        GID = dr["GID"].ToString(),
                        GroupName = dr["GroupName"].ToString(),
                        Descr = dr["Descr"].ToString()
                    });
                }
            }

            ViewBag.Groups = Groups;

            return View(users);
        }

        [ChildActionOnly]
        public ActionResult IndexTable()
        {
            return PartialView();
        }

        /// <summary>
        /// 更改用户状态（正常/停用）
        /// </summary>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("更改用户状态")]
        [TBMAuthorize("用户管理", "更改用户状态")]
        public JsonResult ChangeUserStatus()
        {
            JsonResult result = new JsonResult();
            Models.ExecuteResult er = new Models.ExecuteResult();
            string uid = Request["uid"];
            bool status = false;

            if (String.IsNullOrEmpty(uid) ||
                Request["status"] == null ||
                !bool.TryParse(Request["status"].ToString(), out status)
                )
            {
                er.Result = false;
                er.Code = Core.Lang.REQUEST_INFO_INCOMPLETE.Code;
                er.Message = Core.Lang.REQUEST_INFO_INCOMPLETE.Message;
                result.Data = er;
                return result;
            }

            cmd.CommandText = "update dbo.Users set IsActive = @Status where UID = @UID";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Clear();
            cmd.Parameters.Add("@Status", SqlDbType.Bit);
            cmd.Parameters.Add("@UID", SqlDbType.VarChar, 15);
            cmd.Parameters["@Status"].Value = status;
            cmd.Parameters["@UID"].Value = uid;

            try
            {
                er.Result = cmd.ExecuteNonQuery() > 0;
                Core.LangItem resultItem = er.Result ? Core.Lang.CMD_SUCCESS : Core.Lang.CMD_FAILED;
                er.Code = resultItem.Code;
                er.Message = resultItem.Message;
            }
            catch
            {
                er.Result = false;
                er.Code = Core.Lang.CMD_EXCEPTION.Code;
                er.Message = Core.Lang.CMD_EXCEPTION.Message;
            }

            result.Data = er;

            return result;
        }

        /// <summary>
        /// 重置用户密码
        /// </summary>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("重置用户密码")]
        [TBMAuthorize("用户管理", "重置用户密码")]
        public JsonResult ResetUsersPassword()
        {
            JsonResult result = new JsonResult();
            Models.ExecuteResult er = new Models.ExecuteResult();
            string uids = Request["uids"] == null ? null : Request["uids"].ToString();
            string chkPwd = Request["chkpwd"] == null ? null : Request["chkpwd"].ToString();
            Dictionary<MailAddress, string> emailList = new Dictionary<MailAddress, string>();

            if (uids == null)
            {
                er.Result = true;
                er.Code = Core.Lang.REQUEST_DONE.Code;
                er.Message = Core.Lang.REQUEST_DONE.Message;
                result.Data = er;

                return result;
            }

            if (!Core.App.CheckPassword(chkPwd))
            {
                er.Result = false;
                er.Code = Core.Lang.REQUEST_CHECK_PWD_FAILED.Code;
                er.Message = Core.Lang.REQUEST_CHECK_PWD_FAILED.Message;
                result.Data = er;

                return result;
            }

            string[] uidArray = uids.Split(',');
            cmd.CommandText = "p_ResetPassword";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Clear();
            cmd.Parameters.Add("@UID", SqlDbType.VarChar, 15);
            cmd.Parameters.Add("@NewPassword", SqlDbType.Char, 32);

            List<string> failedSendList = new List<string>();
            string bodyHTML = @"亲爱的{0}，
                                <p>　　您好！</p>
                                <p>　　您的密码已被修改为：{1}，您的UID为：{2}，请尽快登陆修改！</p>
                                <p style=""color: #ff0000;"">　　{3}系统邮件，请勿回复</p>
                                <p>{3}</p>";

            foreach (string uid in uidArray)
            {
                char[] newPassword = new char[8];
                Random random = new Random();

                for (int i = 0; i < newPassword.Length; i++)
                {
                    newPassword[i] = (char)(97 + random.Next(26));
                }

                StringBuilder newpwd = new StringBuilder();
                newpwd.Append(newPassword);

                cmd.Parameters["@UID"].Value = uid;
                cmd.Parameters["@NewPassword"].Value = Core.App.GetPassword(newpwd.ToString());

                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    if (dr.Read())
                    {
                        MailAddress address = new MailAddress(dr["Email"].ToString(), dr["FullName"].ToString(), Encoding.UTF8);
                        if (!Core.App.SendEmail("您的登陆密码已被修改", String.Format(bodyHTML, address.DisplayName, newpwd, uid, Core.Config.SMTPDisplayName), address).Result)
                        {
                            failedSendList.Add(uid);
                        }
                    }

                    dr.Close();
                }
            }

            er.Result = true;
            er.Code = Core.Lang.REQUEST_DONE.Code;
            er.Message = Core.Lang.REQUEST_DONE.Message;
            er.Data = failedSendList.ToArray();
            result.Data = er;

            return result;
        }

        /// <summary>
        /// 添加新用户
        /// </summary>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("添加新用户")]
        [TBMAuthorize("用户管理", "添加新用户")]
        public JsonResult Add()
        {
            JsonResult result = new JsonResult();

            var form = Request.Params;

            if (Core.CommandParamType.IsRequestNullOrEmpty(form["uid"]) ||
                Core.CommandParamType.IsRequestNullOrEmpty(form["password"]) ||
                Core.CommandParamType.IsRequestNullOrEmpty(form["firstname"]) ||
                Core.CommandParamType.IsRequestNullOrEmpty(form["lastname"]) ||
                Core.CommandParamType.IsRequestNullOrEmpty(form["email"]))
            {
                result.Data = new Models.ExecuteResult
                {
                    Result = false,
                    Code = Core.Lang.FORM_INCOMPLETE.Code,
                    Message = Core.Lang.FORM_INCOMPLETE.Message
                };

                return result;
            }

            string uid = form["uid"].ToString().ToLower();
            string password = Core.App.GetPassword(form["password"].ToString());
            string firstname = form["firstname"].ToString();
            string lastname = form["lastname"].ToString();
            string email = form["email"].ToString();

            var avatarFile = Request.Files["avatar"];
            string avatarPath = "";
            string avatarStorePath = "";
            if (avatarFile != null)
            {
                avatarStorePath = Core.Config.FileDirectory + "avatar/" + uid + "/";
                // 头像存储位置
                avatarPath = Server.MapPath(avatarStorePath);

                avatarStorePath = avatarStorePath.TrimStart(new char[] { '~' });

                if (!Directory.Exists(avatarPath)) Directory.CreateDirectory(avatarPath);
            }

            try
            {
                cmd.CommandText = "p_CreateUser";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Clear();

                cmd.Parameters.Add("@UID", SqlDbType.VarChar, 15);
                cmd.Parameters.Add("@Password", SqlDbType.Char, 32);
                cmd.Parameters.Add("@FirstName", SqlDbType.NVarChar, 15);
                cmd.Parameters.Add("@LastName", SqlDbType.NVarChar, 15);
                cmd.Parameters.Add("@PicUrl", SqlDbType.VarChar, 50);
                cmd.Parameters.Add("@Email", SqlDbType.VarChar, 100);
                cmd.Parameters.Add("@Phone", SqlDbType.VarChar, 11);
                cmd.Parameters.Add("@QQ", SqlDbType.VarChar, 11);
                cmd.Parameters.Add("@IsActive", SqlDbType.Bit);
                cmd.Parameters.Add("@Memo", SqlDbType.NVarChar, 200);
                cmd.Parameters.Add("@CNName", SqlDbType.Bit);
                cmd.Parameters.Add("@Groups", SqlDbType.VarChar, 500);
                cmd.Parameters.Add("@Return", SqlDbType.Int);

                cmd.Parameters["@UID"].Value = uid;
                cmd.Parameters["@Password"].Value = password;
                cmd.Parameters["@FirstName"].Value = firstname;
                cmd.Parameters["@LastName"].Value = lastname;
                cmd.Parameters["@PicUrl"].Value = Core.CommandParamType.NullOrString(avatarStorePath);
                cmd.Parameters["@Email"].Value = email;
                cmd.Parameters["@Phone"].Value = Core.CommandParamType.NullOrString(Request["phone"]);
                cmd.Parameters["@QQ"].Value = Core.CommandParamType.NullOrString(Request["qq"]);
                cmd.Parameters["@IsActive"].Value = Core.CommandParamType.Boolean(Request["isactive"]);
                cmd.Parameters["@Memo"].Value = Core.CommandParamType.NullOrString(Request["memo"]);
                cmd.Parameters["@CNName"].Value = Core.CommandParamType.Boolean(Request["cnname"]);
                cmd.Parameters["@Groups"].Value = Core.CommandParamType.NullOrString(Request["groups"]);
                cmd.Parameters["@Return"].Direction = ParameterDirection.ReturnValue;

                int NonQuery = cmd.ExecuteNonQuery();
                Core.LangItem rsp = null;
                Models.ExecuteResult er = new Models.ExecuteResult();
                er.Result = false;

                switch ((int)cmd.Parameters["@Return"].Value)
                {
                    case 0:
                        rsp = NonQuery > 0 ? Core.Lang.CMD_CREATE_USER_SUCCESS : Core.Lang.CMD_CREATE_USER_FAILED;
                        er.Result = NonQuery > 0;
                        break;
                    case 1:
                        rsp = Core.Lang.CMD_UID_EXISTS;
                        break;
                    case 2:
                        rsp = Core.Lang.CMD_EMAIL_EXISTS;
                        break;
                    case 3:
                        rsp = Core.Lang.CMD_UID_EMAIL_EXISTS;
                        break;
                }

                er.Code = rsp.Code;
                er.Message = rsp.Message;
                result.Data = er;

                if (avatarFile != null && er.Result)
                {
                    ImageScaling isc = new ImageScaling(avatarFile.InputStream);

                    isc.ScaleToSave(avatarPath + "large.png", 125, 125, System.Drawing.Imaging.ImageFormat.Png);
                    isc.ScaleToSave(avatarPath + "small.png", 30, 30, System.Drawing.Imaging.ImageFormat.Png);

                    avatarFile.InputStream.Close();
                }
            }
            catch
            {
                if (avatarFile != null) Directory.Delete(avatarPath, true);
                result.Data = new Models.ExecuteResult
                {
                    Result = false,
                    Code = Core.Lang.CMD_EXCEPTION.Code,
                    Message = Core.Lang.CMD_EXCEPTION.Message
                };
            }

            return result;
        }

        /// <summary>
        /// 批量删除用户
        /// </summary>
        /// <param name="chkpwd">确认用户密码</param>
        /// <param name="uids">被删除的用户UID</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("删除用户")]
        [TBMAuthorize("用户管理", "删除用户")]
        public JsonResult Delete(string chkpwd, string[] uids)
        {
            JsonResult result = new JsonResult();

            if (!Core.App.CheckPassword(chkpwd))
            {
                result.Data = new Models.ExecuteResult
                {
                    Result = false,
                    Code = Core.Lang.REQUEST_CHECK_PWD_FAILED.Code,
                    Message = Core.Lang.REQUEST_CHECK_PWD_FAILED.Message
                };

                return result;
            }

            cmd.CommandText = "delete from dbo.Users where UID = @UID";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Clear();
            cmd.Parameters.Add("@UID", SqlDbType.VarChar, 15);

            List<string> errList = new List<string>();
            string avatarDirectory = Core.Config.FileDirectory + "avatar/";

            foreach (string uid in uids)
            {
                cmd.Parameters["@UID"].Value = uid;

                if (uid != CurrUser.UID && cmd.ExecuteNonQuery() > 0)
                {
                    string avatarPath = Server.MapPath(avatarDirectory + uid + "/");
                    if (Directory.Exists(avatarPath)) Directory.Delete(avatarPath, true);
                }
                else
                {
                    errList.Add(uid);
                }
            }

            result.Data = new Models.ExecuteResult
            {
                Result = true,
                Code = Core.Lang.DELETE_USER_SUCCESS.Code,
                Message = Core.Lang.DELETE_USER_SUCCESS.Message,
                Data = errList.ToArray()
            };

            return result;
        }

        /// <summary>
        /// 添加用户到组
        /// </summary>
        /// <param name="gids">组ID列表</param>
        /// <param name="uids">被添加用户ID列表</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("添加用户到组")]
        [TBMAuthorize("用户管理", "添加用户到组")]
        public JsonResult AppendToGroup(string[] gids, string[] uids)
        {
            return _UserToGroup(gids, uids);
        }

        /// <summary>
        /// 用户详细信息
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("用户详细信息")]
        [TBMAuthorize("用户管理", "用户详细信息")]
        public ActionResult UserDetail(string uid)
        {
            cmd.CommandText = @"select 
	                                UID, 
	                                (select 
                                            case ROW_NUMBER() over(order by G.GID) 
                                                when 1 then '' else ', ' end + 
                                                G.GroupName as 'text()' 
                                            from 
                                                dbo.MemberShip as M inner join dbo.Groups as G on M.GID = G.GID 
                                            where M.UID = U.UID for xml path('')) as Groups,
	                                FirstName, LastName, PicUrl, Email, Phone, QQ, RegisterDate, IsActive, Memo, CNName 
                                from dbo.Users as U where UID = @UID";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Clear();
            cmd.Parameters.Add("@UID", SqlDbType.VarChar, 15);
            cmd.Parameters["@UID"].Value = uid;

            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                ViewBag.UserInfo = dr.Read() ? new Models.User
                {
                    UID = dr["UID"].ToString(),
                    Groups = dr["Groups"].ToString(),
                    FirstName = dr["FirstName"].ToString(),
                    LastName = dr["LastName"].ToString(),
                    PicUrl = dr["PicUrl"].ToString(),
                    Email = dr["Email"].ToString(),
                    Phone = dr["Phone"].ToString(),
                    QQ = dr["QQ"].ToString(),
                    RegisterDate = Convert.ToDateTime(dr["RegisterDate"]),
                    IsActive = (bool)dr["IsActive"],
                    Memo = dr["Memo"].ToString(),
                    CNName = (bool)dr["CNName"]
                } : null;
            }

            if (ViewBag.UserInfo == null)
            {
                return RedirectToAction("C500", "Error");
            }

            cmd.CommandText = @"select G.GID, GroupName, Descr, cast(case when M.GID is null then 0 else 1 end as bit) as IsChecked 
                                    from dbo.Groups as G left join dbo.MemberShip as M on G.GID = M.GID and M.UID = @UID";
            cmd.CommandType = CommandType.Text;

            List<Models.Group> Groups = new List<Models.Group>();

            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    Groups.Add(new Models.Group
                    {
                        GID = dr["GID"].ToString(),
                        GroupName = dr["GroupName"].ToString(),
                        Descr = dr["Descr"].ToString(),
                        IsChecked = (bool)dr["IsChecked"]
                    });
                }
            }

            ViewBag.Groups = Groups;

            cmd.CommandText = "p_ModulesInUser";
            cmd.CommandType = CommandType.StoredProcedure;
            List<Models.Module> Modules = new List<Models.Module>();
            Dictionary<Models.Module, List<Models.Module>> ModuleList = new Dictionary<Models.Module, List<Models.Module>>();

            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    Modules.Add(new Models.Module
                    {
                        ID = (int)dr["ID"],
                        PID = (int)dr["PID"],
                        ControllerName = dr["ControllerName"].ToString(),
                        ControllerDescr = dr["ControllerDescr"].ToString(),
                        ActionName = dr["ActionName"].ToString(),
                        ActionDescr = dr["ActionDescr"].ToString(),
                        IsActived = (bool)dr["IsActived"],
                        IsChecked = (bool)dr["IsChecked"]
                    });
                }
            }

            foreach (Models.Module module in Modules.Where(item => item.PID == 0))
            {
                ModuleList.Add(module, Modules.Where(item => item.PID == module.ID).ToList());
            }

            ViewBag.ModuleList = ModuleList;
            ViewBag.IsCurrentUser = CurrUser.UID == uid;
            ViewBag.MainMenu = GetObjectMenu(uid, 0);

            return View();
        }

        /// <summary>
        /// 更新用户头像
        /// </summary>
        /// <param name="uid">用户UID</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("更新用户头像")]
        [TBMAuthorize("用户管理", "更新用户头像")]
        public JsonResult UpdateAvatar(string uid)
        {
            return _UpdateAvatar(uid);
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="uid">用户UID</param>
        /// <param name="firstname">姓氏</param>
        /// <param name="lastname">名字</param>
        /// <param name="email">Email</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("更新用户信息")]
        [TBMAuthorize("用户管理", "更新用户信息")]
        public JsonResult UpdateUser(string uid, string firstname, string lastname, string email)
        {
            return _UpdateUser(uid, firstname, lastname, email, true);
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="uid">用户UID</param>
        /// <param name="newpassword">新的密码</param>
        /// <param name="currpassword">当前密码</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("修改用户密码")]
        [TBMAuthorize("用户管理", "修改用户密码")]
        public JsonResult UpdatePWD(string uid, string newpassword, string currpassword)
        {
            return _UpdatePWD(uid, newpassword, currpassword);
        }

        /// <summary>
        /// 更新用户权限
        /// </summary>
        /// <param name="uid">用户UID</param>
        /// <param name="moduleid">被勾选的模块ID</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("更新用户模块权限")]
        [TBMAuthorize("用户管理", "更新用户模块权限")]
        public JsonResult UpdateUserPermission(string uid)
        {
            return _UpdatePermission(uid);
        }


        /// <summary>
        /// 更新用户权限
        /// </summary>
        /// <param name="gid">用户UID</param>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("更新用户页面权限")]
        [TBMAuthorize("用户管理", "更新用户页面权限")]
        public JsonResult UpdateUserMenuPermission(string uid)
        {
            return _UpdateMenuPermission(uid);
        }


        /// <summary>
        /// 导出用户数据到Excel
        /// </summary>
        /// <returns></returns>
        [ParentAction("Index")]
        [Description("导出用户Excel")]
        [TBMAuthorize("用户管理", "导出用户Excel")]
        public ExcelResult ExportUsers()
        {
            DataSet ds = new DataSet();

            cmd.CommandText = @"select 
	                                UID, case when CNName = 1 then FirstName + LastName else LastName + ' ' + FirstName end as 姓名, 
	                                Email, Phone as 联系电话, QQ, RegisterDate as 注册时间, case when IsActive = 1 then '正常' else '停用' end as 状态, 
	                                Memo as 备注
                                from dbo.Users";
            cmd.CommandType = CommandType.Text;

            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataTable dt = new DataTable("用户列表");
            da.Fill(dt);

            ds.Tables.Add(dt);

            return new ExcelResult(ds, "用户列表");
        }
    }
}
